/*
 * Copyright (c) 2011, Nikolaus Moll
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * * Neither the name of the gradecalculator.net nor the
 *   names of its contributors may be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
package net.gradecalculator.plugin.core.stux.internal;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import net.gradecalculator.plugin.loader.exceptions.PluginException;

@XmlRootElement(namespace = "http://gradecalculator.net/", name="student")
@XmlType( 
 propOrder = { "name", "universityName", "degree", "courseOfStudies", "semester", "selectedModuleLists", "results" } 
)
public class XmlStudent {
	private String name;
	private String universityName;
	private String degree;	// Master, Bachelor, ...
	private String courseOfStudies;
	private String semester;	// version of regulations
	private List<String> selectedModuleLists = new ArrayList<String>();
	private List<XmlExaminationResult> results = new ArrayList<XmlExaminationResult>();
	
	public String getName() {
		return name;
	}
	public void setName(final String name) {
		this.name = name;
	}

	public String getSemester() {
		return semester;
	}
	public void setSemester(final String semester) {
		this.semester = semester;
	}

	@XmlElementWrapper(name="selections")
	@XmlElement(name="selection")
	public List<String> getSelectedModuleLists() {
		return selectedModuleLists;
	}
	public void setSelectedModuleLists(final List<String> selectedModuleLists) {
		this.selectedModuleLists = selectedModuleLists;
	}

	@XmlElementWrapper(name="results")
	@XmlElement(name = "result")
	public List<XmlExaminationResult> getResults() {
		// TODO: remove unnecessary results...
		final List<XmlExaminationResult> workingcopy = new ArrayList<XmlExaminationResult>(results);
		for (XmlExaminationResult r : workingcopy) {
			//	remove unnecessary items
			final boolean keep = (r.getGrades().size() > 0) || (r.getUngradedPassed());
			if (!keep) {
				results.remove(r);
			}
		}
		return results;
	}
	public void setResults(final List<XmlExaminationResult> results) {
		this.results = results;
	}

	@XmlElement(name = "university")
	public String getUniversityName() {
		return universityName;
	}
	public void setUniversityName(final String university) {
		this.universityName = university;
	}

	@XmlElement(name = "courseofstudies")
	public String getCourseOfStudies() {
		return courseOfStudies;
	}
	public void setCourseOfStudies(final String courseOfStudies) {
		this.courseOfStudies = courseOfStudies;
	}
	
	public String getDegree() {
		return degree;
	}
	public void setDegree(final String degree) {
		this.degree = degree;
	}

	public static XmlStudent createFromXML(final String filename) {
		Reader xmlinput = null;
		XmlStudent result = null;
		try {
			final JAXBContext context = JAXBContext.newInstance(XmlStudent.class);
			final Unmarshaller unmarshaller = context.createUnmarshaller();
			xmlinput = new FileReader(filename);
			result = (XmlStudent) unmarshaller.unmarshal(xmlinput);
		} catch (final JAXBException jaxbException) {
			throw new PluginException("Error reading student xml", jaxbException);
		} catch (final Exception e) {
			throw new PluginException("Error reading student xml", e);
		} finally {
			try {
				if (xmlinput != null) {
					xmlinput.close();
				}
			} catch (final IOException e) {
				throw new PluginException("Error closing student xml", e);
			}
		}
		return result;
	}

	public void saveXML(final String filename) {
		Writer xmloutput = null;
		try {
			final XmlStudent student = this;
			
			final JAXBContext context = JAXBContext.newInstance(XmlStudent.class);
			final Marshaller marshaller = context.createMarshaller();
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
			xmloutput = new FileWriter(filename);
			marshaller.marshal(student, xmloutput);
			xmloutput.flush();
		} catch (final JAXBException jaxbException) {
			throw new PluginException("Error writing student xml", jaxbException);
		} catch (final Exception e) {
			throw new PluginException("Error saving student xml", e);
		} finally {
			try {
				if (xmloutput != null) {
					xmloutput.close();
				}
			} catch (final Exception e) {
				throw new PluginException("Error closing student xml", e);
			}
		}
	}
	
}
